#ifndef __EKOS_SYSCALL_H__
#define __EKOS_SYSCALL_H__

#define INT_SYSCALL 0x80
#define INT_YIELD   0x81
#define INT_KCB_RET 0x82
#define INT_IPI     0x83

#define IPS_NO_WAIT    0
#define IPS_WAIT_INT   1
#define IPS_WAIT       2

/* TEMPORERY ROUTINES ========================================= */
/* kprintf(fmt, ...)
 *
 * Print information to console/serial port, this function is only
 * used for low level debugging.
 *
 * ret: void
 */
#define SC_KPRINTF 0x00

/* APPLICATION ROUTINES ======================================= */
/* send(ap, ips-offset, arg, payload-page)
 *
 * Send data to access point ``ap'' using the specified queue node,
 * with passing the argument ``arg'' and a page located at
 * ``payload-page'', ``payload-page'' == NULL means no argument.
 *
 * ret:
 *   -E_BUSY  the ``ips'' node is in use
 *   -E_PERM  permission denied
 *   -E_INVAL wrong ap num, ips-offset or payload-page
 *    0       OK
 */
#define SC_SEND 0x10

/* send_try(ips, wait)
 *
 * Test whether the sending associated with ``ips'' node is
 * finished. ``ips'' is released IIF the send_try func returns 0 or
 * -E_INTERRUPTED. It may also return -E_AGAIN to indicate the need of
 * repeat of the call. Pass wait = 0 if you do not plan to wait.
 *
 * ret:
 *   -E_INVAL the ips is not in use, or not used for sending
 *   -E_AGAIN the control is returned, the sending may not be finished
 *   -E_INTERRUPT the sending is breaked, ``ips'' is free now
 *    0       the sending is finished, ``ips'' is free now
 */
#define SC_SEND_TRY 0x11

/* send_break(ips)
 *
 * Break the sending of ``ips'' node. Calls to the send_try after
 * send_break with same ips node would return -E_INTERRUPTED.
 *
 * ret:
 *   -E_INVAL the ips is not in use, or not used for sending
 *    0       the ``ips'' is interrupted
 */
#define SC_SEND_BREAK 0x12

/* missing */
#define SC_WAIT_PRETEND   0x13
#define SC_WAIT_TRY       0x14

/* wait(lock)
 * 
 * Turn self process into waiting state, and release the spinlock
 * ``lock'' if it is valid in userspace.
 *
 * ret: void
 */
#define SC_WAIT 0x15

/* notify(proc)
 *
 * Notify the specified process ``proc''.
 *
 * ret: void
 */
#define SC_NOTIFY 0x16

/* doc missing */
#define SC_SET_PROC_ATTR 0x17

#define PA_SIGNAL_FLAGS   0x00
#define PA_SIGNAL_HANDLER 0x01

/* signal(proc)
 *
 * Send a signal to process ``proc''.
 * ret: void
 */
#define SC_SIGNAL 0x18
#define SC_EXIT 0x19

/* SERVICE PROVIDER ROUTINES ================================== */
/* recv(ap, ips)
 *
 * Wait for recieving data on access point ``ap'', with ``ips'' queue
 * node.
 *
 * ret:
 *   -E_PERM  permission denied
 *   -E_BUSY  ips not free
 *   -E_INVAL wrong ap num
 *    0       OK
 */
#define SC_RECV 0x20

/* recv_try(ips, vaddr, wait)
 * 
 * Check the recv of ``ips'' to be finished or interrupt. Set wait = 0
 * if you would not do wait for it. It would map the passing data to
 * vaddr.
 *
 * ret:
 *   -E_INVAL the ips is not in use, or not used for recving
 *   -E_AGAIN the control is returned, the recving may not be finished
 *   -E_INTERRUPT the recving is breaked, ``ips'' is free now
 *    0       the recv is finished, ``ips'' is free now
 */
#define SC_RECV_TRY 0x21

/* recv_break(ips)
 *
 * Break the waiting of recv on ips ``ips''.
 *
 * ret:
 *   -E_INVAL the ips is not used for recv
 *    0       OK
 */
#define SC_RECV_BREAK 0x22

/* MANAGERS ROUTINES ========================================== */
/* proc_fork(proc, code, stack)
 *
 * Create a proc with same env with ``proc'' and initial
 * parameter. With specified code and stack entry.
 *
 * ret:
 *   -E_PERM    permission denied
 *   -E_NO_PROC the system resource for proc is depleted
 *    >= 0      the forked proc num
 */
#define SC_PROC_FORK 0x31

/* proc_kill(proc)
 *
 * Kill the process ``proc'' and release the resource for the process
 * in kernel.
 *
 * ret:
 *   -E_PERM     permission denied
 *   -E_BAD_PROC the process is already free
 *    0          success
 */
#define SC_PROC_KILL 0x32

/* env_create(flags, priority, code_entry, stack_entry)
 *
 * Create a new env with given vpt at ``paddr'', ``code_entry''
 * for code entry and ``stack_entry'' for stack
 *
 * ret:
 *   -E_PERM     permission denied
 *   -E_NORES    resource shortage
 *    0          success
 */
#define SC_ENV_CREATE 0x33

/* env_free(env)
 *
 * release the env structure.
 *
 * ret:
 *   -E_PERM
 *    0
 */
#define SC_ENV_FREE 0x34

/* proc_attach(proc)
 *
 * Attach detached proc to current lcpu schedule cycle
 *
 * ret:
 *   -E_PERM
 *   -E_INVAL
 *    0
 */
#define SC_PROC_ATTACH 0x35

/* proc_detach(proc)
 *
 * Detach specified proc on current lcpu from schedule cycle
 *
 * ret:
 *   -E_PERM
 *   -E_INVAL
 *    0
 */
#define SC_PROC_DETACH 0x36

/* proc_invoke(proc, lcpu)
 *
 * Invoke specified process ``proc'' on cpu ``lcpu''
 *
 * ret:
 *   -E_PERM
 *    0
 */
#define SC_PROC_INVOKE 0x37

/* proc_invoke_all(procs_block)
 *
 * Invoke all lcpu to switch to corresponding processes in the
 * ``procs_block''
 *
 * ret:
 *   -E_PERM
 *    0
 */
#define SC_PROC_INVOKE_ALL 0x38

/* mmap_set(proc, vaddr, paddr, perm)
 *
 * Set the virtual memory map for process ``proc''. Map linear address
 * ``vaddr'' to ``paddr'' with permission ``perm''
 *
 * ret:
 *   -E_PERM
 *   -E_INVAL
 *    0
 */
#define SC_MMAP_SET 0x39
#define SC_MMAP_SET_PERM_WRITE 2

/* ppage_alloc(num, core)
 *
 * Alloc memory ``num'' pages from system, core == 0 indicates that
 * the memory will be managed by application. Or the memory is managed
 * by ref-count
 *
 * ret:
 *   -E_PERM
 *   -E_NO_MEM
 *    >= 0
 */
#define SC_PPAGE_ALLOC 0x3a

/* ppage_free(addr)
 *
 * Free the pages started at ``addr'' to system.
 *
 * ret:
 *   -E_PERM  permission error
 *   -E_INVAL the memory is managed by system, or it's already free
 *    0       success
 */
#define SC_PPAGE_FREE 0x3b

#define SC_SET_SOFT_TIMER 0x3c

#define SC_NOTIFY_EX 0x3d

#define SC_MAX	        0xFF

#define IPI_IDLE        0x00
#define IPI_INVOKE      0x01
#define IPI_INVOKE_ALL  0x02

#endif
